package ph.com.gs3.formalistics.fragments.workers;

import ph.com.gs3.formalistics.communicators.CommunicatorModule.ResultCode;
import ph.com.gs3.formalistics.managers.SessionManager;
import ph.com.gs3.formalistics.managers.SessionManager.ConnectivityType;
import ph.com.gs3.formalistics.managers.SessionManager.LoginResult;
import ph.com.gs3.formalistics.managers.SessionManager.Mode;
import ph.com.gs3.formalistics.managers.SessionManager.SessionManagerEventListener;
import ph.com.gs3.formalistics.model.valueobjects.business.User;
import ph.com.gs3.formalistics.utilities.FLLogger;
import ph.com.gs3.formalistics.utilities.FLLogger.LogType;
import android.app.Activity;
import android.os.AsyncTask;
import android.support.v4.app.Fragment;

public class MainWorkerFragment extends Fragment implements SessionManagerEventListener {

	public static final String TAG = MainWorkerFragment.class.getSimpleName();

	public static enum SessionStatus {
		LOGGED_IN, NO_SESSION
	}

	private SessionManager sessionMan;

	private MainWorkerFragmentListener listener;

	private User activeUser;
	private SessionStatus status;

	public static MainWorkerFragment createInstance(User activeUser, SessionStatus sessionStatus) {

		MainWorkerFragment mainWorkerFragment = new MainWorkerFragment();
		mainWorkerFragment.activeUser = activeUser;
		mainWorkerFragment.status = sessionStatus;

		return mainWorkerFragment;

	}

	public MainWorkerFragment() {}

	public void initialize() {
		sessionMan = SessionManager.getApplicationInstance();
		sessionMan.addListener(this);
	}

	// ========================================================================
	// Functional Methods

	public void notifySessionLost() {

		status = SessionStatus.NO_SESSION;
		checkSession();

	}

	public void checkSession() {

		boolean needsReauthentication = true;
		boolean isCurrentlyLoggingIn = false;

		if (status == SessionStatus.NO_SESSION
		        && (sessionMan.getConnecctivityType() == ConnectivityType.MOBILE_DATA || sessionMan
		                .getConnecctivityType() == ConnectivityType.WIFI)) {

			FLLogger.log(TAG, LogType.MESSAGE, "online mode");
			if (activeUser == null) {
				// get the last active user and try logging in using that account
				activeUser = sessionMan.getLastActiveUser();
			}

			// check if there is a last active user, if there is non, the user needs
			// to re-authenticate manually, if the user is found, try logging in using
			// that user.
			if (activeUser != null) {

				autoLogin(activeUser);
				isCurrentlyLoggingIn = true;

			} else {
				FLLogger.log(TAG, LogType.MESSAGE, "no active user");
			}

		} else {
			needsReauthentication = false;
		}

		if (needsReauthentication && !isCurrentlyLoggingIn) {
			listener.onUserNeedsToReauthenticate(null);
		}

	}

	private void autoLogin(final User lastActiveUser) {

		listener.onApplicationIsReAuthenticating(lastActiveUser);

		AsyncTask<Void, Void, LoginResult> loginTask = new AsyncTask<Void, Void, LoginResult>() {

			@Override
			protected LoginResult doInBackground(Void... params) {

				// try to re-authenticate using the last active account

				String server = lastActiveUser.getAccountServer();
				String email = lastActiveUser.getEmail();
				String password = lastActiveUser.getPassword();// TODO: add a
				                                               // decryption task here

				LoginResult loginResult = sessionMan.login(server, email, password);

				return loginResult;
			}

			@Override
			protected void onPostExecute(LoginResult loginResult) {
				super.onPostExecute(loginResult);

				if (loginResult.loginResultCode == ResultCode.SUCCESS) {
					listener.onApplicationReAuthenticated(loginResult.activeUser);
				} else {
					listener.onUserNeedsToReauthenticate(loginResult);
				}

			}

		};

		loginTask.execute();
		FLLogger.d(TAG, "Auto login task started");

	}

	// ========================================================================
	// Implementation Methods

	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);

		// register the activity as the mode change listener
		try {
			listener = (MainWorkerFragmentListener) activity;
			initialize();
			checkSession();
		} catch (ClassCastException e) {
			throw new ClassCastException(activity.toString() + " must implement ModeChangeListener");
		}

	}

	@Override
	public void onModeChanged(Mode mode) {
		listener.onModeChanged(mode);
	}

	@Override
	public void onSessionLost() {
		// listener.onUserNeedsToReauthenticate();
	}

	// ========================================================================
	// Interfaces

	public static interface MainWorkerFragmentListener {

		public void onUserNeedsToReauthenticate(LoginResult loginResult);

		public void onApplicationIsReAuthenticating(User user);

		public void onApplicationReAuthenticated(User user);

		public void onModeChanged(Mode mode);

	}

}
